#include "parse.h"

bool parse(char *filename){

	int instances, nets, inputs, outputs;
	const int MAX_LINE_LENGTH       = 65536;
  
        cout << "Reading file..." << endl;
        char line_buffer[MAX_LINE_LENGTH];
 
        int line_num = 0;
        int index = 0;
  
        ifstream inp(filename);
        if (!inp.is_open()) {
                cerr << "Can't open input file" << endl;
                exit(1);
        }
	
	inp.getline(line_buffer, MAX_LINE_LENGTH);
	//cout<<line_buffer<<endl;
	++line_num;
	int arg = sscanf(line_buffer, "## No of instances %d", &instances);
	inp.getline(line_buffer, MAX_LINE_LENGTH);
	//cout<<line_buffer<<endl;
	++line_num;
	arg = sscanf(line_buffer, "## No of Nets %d", &nets);
	inp.getline(line_buffer, MAX_LINE_LENGTH);
	//cout<<line_buffer<<endl;
	++line_num;
	arg = sscanf(line_buffer, "## No of Inputs %d", &inputs);
	inp.getline(line_buffer, MAX_LINE_LENGTH);
	//cout<<line_buffer<<endl;
	++line_num;
	arg = sscanf(line_buffer, "## No of Outputs %d", &outputs);
	
	inp.getline(line_buffer, MAX_LINE_LENGTH);
	for(int i=0; i<3; ++i){
		inp.getline(line_buffer, MAX_LINE_LENGTH);
		++line_num;
	}
	//cout<<instances<<','<<nets<<','<<inputs<<','<<outputs<<endl;
	//cin.get();
	C = new Circuit();
	///inputs
	for(int i=0; i<inputs; ++i){
		string tmp;
		inp.getline(line_buffer, MAX_LINE_LENGTH);
                //	cout<<i<<':'<<line_buffer<<endl;
		++line_num;
		int cnt=0;
		while(line_buffer[cnt++]!='(') {}
		while(line_buffer[cnt]!=')')
			tmp += line_buffer[cnt++];
		Signal *s=C->addSignal(tmp);
		InputNode *n = new InputNode();
		n->setIndex(index++);
		s->addOutput(n);
		n->addInput(s);
		C->addInput(n);	
	}
	/*
          string tmp = " ";
          Signal *s=C->addSignal(tmp);
          InputNode *n = new InputNode();
          n->setIndex(index++);
          s->addOutput(n);
          n->addInput(s);
          C->addInput(n);	
          inputs++;
	*/
	///outputs
	for(int i=0; i<outputs; ++i){
		string tmp;
		inp.getline(line_buffer, MAX_LINE_LENGTH);
                //	cout<<i<<':'<<line_buffer<<endl;
		++line_num;
		int cnt=0;
		while(line_buffer[cnt++]!='('){}
		while(line_buffer[cnt]!=')')
			tmp += line_buffer[cnt++];
		Signal *s=C->addSignal(tmp);
		OutputNode *n = new OutputNode();
		n->setIndex(index++);
		n->addOutput(s);
		C->addOutput(n);		
		s->addInput(n);
	}
	
	for(int i=0; i<2; ++i){
		inp.getline(line_buffer, MAX_LINE_LENGTH);
                //	cout<<i<<':'<<line_buffer<<endl;
		++line_num;
	}	
	///instances
	for(int i=0; i<instances; ++i){
		
		inp.getline(line_buffer, MAX_LINE_LENGTH);
                //	cout<<i<<':'<<line_buffer<<endl;
		++line_num;
		if(line_buffer[0]=='('){ //flipflop
			FlipflopNode *n = new FlipflopNode();
			n->setIndex(index++);
			C->addFlipflop(n);
			int cnt=1;
			string tmp;
			while(line_buffer[cnt]!=',')
				tmp += line_buffer[cnt++];
			if(tmp[0] != ' '){
				Signal *s=C->addSignal(tmp);	
				s->addInput(n);
				n->addOutput(s);
			}
			else{
				tmp = "s";
				char buffer [33];
				sprintf (buffer, "%i", C->signalSize());
				tmp += buffer;
				Signal *s=C->addSignal(tmp);
				s->addInput(n);
				n->addOutput(s);
			}
			tmp = "";
			while(line_buffer[++cnt]==' '){}
			while(line_buffer[cnt]!=')')
				tmp += line_buffer[cnt++];
				
			if(tmp.size()){
				Signal *s=C->addSignal(tmp);
				NotNode *n1= new NotNode();
				n->setIndex(index++);
				C->addGate(n1);
				n1->addOutput(s);
				n1->addInput(n->getOutput(0));
				s->addInput(n1);
				n->getOutput(0)->addOutput(n1);
				
			}
			while(line_buffer[cnt++]!='('){}
			tmp="";
			while(line_buffer[cnt]!=',')
				tmp += line_buffer[cnt++];
			Signal *s=C->addSignal(tmp);
			n->addInput(s);
			s->addOutput(n);
			
			tmp="";
			cnt++;
			cnt++;
			while(line_buffer[cnt]!=',')
				tmp += line_buffer[cnt++];
			if(tmp[0]!=' '){
				s=C->addSignal(tmp);
				n->addInput(s);
				s->addOutput(n);
			}
			else{
				tmp = "s";
				char buffer [33];
				sprintf (buffer, "%i", C->signalSize());
				tmp += buffer;
				Signal *s=C->addSignal(tmp);
				
				InputNode *n1=new InputNode();
				n1->setIndex(index++);
				C->addInput(n1);
				s->addOutput(n1);
				n1->addInput(s);
				s->addOutput(n);
				n->addInput(s);				
			}
			
			tmp="";
			cnt++;
			cnt++;
			while((line_buffer[cnt]!=')')&&(line_buffer[cnt]!=','))
				tmp += line_buffer[cnt++];				
			s=C->addSignal(tmp);
			n->addInput(s);
			s->addOutput(n);	
			
                }

                else{ //other gates
                        string tmp;
                        int cnt=0;
                        while(line_buffer[cnt]!=' ')
                                tmp += line_buffer[cnt++];
                        Signal *s=C->addSignal(tmp);
                        cnt += 3;
                        tmp="";
                        for(int i=0; i<5; ++i,cnt++)
                                tmp += line_buffer[cnt];
                        //	cout<<tmp<<endl;
			if(tmp == "INV_X"){
				NotNode *n= new NotNode();
				n->setIndex(index++);
				C->addGate(n);
				n->addOutput(s);
				s->addInput(n);
				while(line_buffer[cnt++]!='('){}
				tmp="";
				while(line_buffer[cnt]!=')')
					tmp += line_buffer[cnt++];
				s=C->addSignal(tmp);
				n->addInput(s);
				s->addOutput(n);	
			}
			else if(tmp == "NAND2"){
				Nand2Node *n=new Nand2Node();
				n->setIndex(index++);
				C->addGate(n);
				n->addOutput(s);
				s->addInput(n);
				tmp="";
				while(line_buffer[cnt++]!='('){}
				while(line_buffer[cnt]!=',')
                                        tmp += line_buffer[cnt++];
				s=C->addSignal(tmp);
				n->addInput(s);
				s->addOutput(n);
				tmp="";
				cnt++;
				cnt++;
				while(line_buffer[cnt]!=')')
					tmp += line_buffer[cnt++];
				s=C->addSignal(tmp);
				n->addInput(s);
				s->addOutput(n);	
			}
			else if(tmp == "NOR2_" ){
				Nor2Node *n=new Nor2Node();
				n->setIndex(index++);
				C->addGate(n);
				n->addOutput(s);
				s->addInput(n);
				tmp="";
				while(line_buffer[cnt++]!='('){}
				while(line_buffer[cnt]!=',')
                                        tmp += line_buffer[cnt++];
				s=C->addSignal(tmp);
				n->addInput(s);
				s->addOutput(n);
				
				tmp="";
				cnt++;
				cnt++;
				while(line_buffer[cnt]!=')')
					tmp += line_buffer[cnt++];
				s=C->addSignal(tmp);
				n->addInput(s);
				s->addOutput(n);	
			}
			else if(tmp=="NAND3"){
				Nand2Node *n1=new Nand2Node();
				n1->setIndex(index++);
				NotNode *n2 = new NotNode();
				n2->setIndex(index++);
				Nand2Node *n3=new Nand2Node();
				n3->setIndex(index++);
				C->addGate(n1);
				C->addGate(n2);
				C->addGate(n3);
				n3->addOutput(s);
				s->addInput(n3);
				
				tmp = "s";
				char buffer [33];
				sprintf (buffer, "%i", C->signalSize());
				tmp += buffer;
				Signal *s1=C->addSignal(tmp);
				n2->addInput(s1);
				s1->addOutput(n2);
				s1->addInput(n1);
				n1->addOutput(s1);
				
				tmp = "s";
				sprintf (buffer, "%i", C->signalSize());
				tmp += buffer;
				Signal *s2=C->addSignal(tmp);
				n2->addOutput(s2);
				s2->addInput(n2);
				s2->addOutput(n3);
				n3->addInput(s2);
				
				while(line_buffer[cnt++]!='('){}
				tmp="";
				while(line_buffer[cnt]!=',')
					tmp += line_buffer[cnt++];
				Signal *s3=C->addSignal(tmp);
				n1->addInput(s3);
				s3->addOutput(n1);
				
				tmp="";
				cnt++;
				cnt++;
				while(line_buffer[cnt]!=',')
					tmp += line_buffer[cnt++];
				Signal *s4=C->addSignal(tmp);
				n1->addInput(s4);
				s4->addOutput(n1);
				
				tmp="";
				cnt++;
				cnt++;
				while(line_buffer[cnt]!=')')
					tmp += line_buffer[cnt++];
				Signal *s5=C->addSignal(tmp);
				n3->addInput(s5);
				s5->addOutput(n3);
			
			}
			else if(tmp=="NOR3_"){
				Nor2Node *n1=new Nor2Node();
				n1->setIndex(index++);
				NotNode *n2 = new NotNode();
				n2->setIndex(index++);
				Nor2Node *n3=new Nor2Node();
				n3->setIndex(index++);
				C->addGate(n1);
				C->addGate(n2);
				C->addGate(n3);
				n3->addOutput(s);
				s->addInput(n3);
				
				tmp = "s";
				char buffer [33];
				sprintf (buffer, "%i", C->signalSize());
				tmp += buffer;
				Signal *s1=C->addSignal(tmp);
				n2->addInput(s1);
				s1->addOutput(n2);
				s1->addInput(n1);
				n1->addOutput(s1);
				
				tmp = "s";
				sprintf (buffer, "%i", C->signalSize());
				tmp += buffer;
				Signal *s2=C->addSignal(tmp);
				n2->addOutput(s2);
				s2->addInput(n2);
				s2->addOutput(n3);
				n3->addInput(s2);
				
				while(line_buffer[cnt++]!='('){}
				tmp="";
				while(line_buffer[cnt]!=',')
					tmp += line_buffer[cnt++];
				Signal *s3=C->addSignal(tmp);
				n1->addInput(s3);
				s3->addOutput(n1);
				
				tmp="";
				cnt++;
				cnt++;
				while(line_buffer[cnt]!=',')
					tmp += line_buffer[cnt++];
				Signal *s4=C->addSignal(tmp);
				n1->addInput(s4);
				s4->addOutput(n1);
				
				tmp="";
				cnt++;
				cnt++;
				while(line_buffer[cnt]!=')')
					tmp += line_buffer[cnt++];
				Signal *s5=C->addSignal(tmp);
				n3->addInput(s5);
				s5->addOutput(n3);
						
			}
			else{
				cout<<line_num<<" has error! "<<line_buffer<<endl;
				exit(1);
			}
		}
	}
	cout<<"## No of FlipFlops:"<<C->flipflopSize()<<endl<<endl;;
	
	if(VERBOSE){
		for(int i=0; i<C->inputSize(); ++i)
			cout<<C->getInput(i)->str()<<endl;
		for(int i=0; i<C->outputSize(); ++i)
			cout<<C->getOutput(i)->str()<<endl;
		for(int i=0; i<C->flipflopSize(); ++i)
			cout<<C->getFlipflop(i)->str()<<endl;
		for(int i=0; i<C->gateSize(); ++i)
			cout<<C->getGate(i)->str()<<endl;
		cout<<"#of Signals: "<<C->signalSize()<<endl;
		
		for(int i=0; i<C->signalSize(); ++i){
			Signal *s=C->getSignal(i);
			cout<<s->str()<<endl;
			//cin.get();
                        //	cout<<"  "<<((s->getOut())? s->getOut()->str():s->getIn()->str())<<endl;
		}
		
/*		for(int i=0; i<C->signalSize(); ++i){
                cout<<C->getSignal(i)->getName()<<":";
                switch (C->getSignal(i)->getOut()->signature()){
                case OUTPUT:
                cout<<"OUTPUT";
                break;
                case INPUT:
                cout<<"INPUT";
                break;
                default:
                cout<<"error";
                }
                }*/
        }
	
	return true;
}

